#
#  Entities.py
#  TurnShip
#
#  Created by Pete Lord on 22/12/2008.
#  Copyright (c) 2008 __MyCompanyName__. All rights reserved.
#
import pygame, Options, Ships, Maps, os, Interfaces, Effects, Clouds, Objects, Graphics, Players

class Cursor(Objects.Object):
    def __init__(self, entities, x=0, y=0):
        Objects.Object.__init__(self, entities, x, y, 0)
        self.x = x
        self.y = y
        self.textures = entities.tile_graphics[os.path.join('Data', 'Tiles', 'Cursor')]
        
    def draw(self):
        # the Ship class should _never_ be instantiated, this funcition will not work without self.textures
        # which is defined as part of the ship class itself.
        return self.textures[Options.ZOOM_LEVEL], pygame.Rect(self.shadow_location(), (Options.SPRITE_SIZE[Options.ZOOM_LEVEL], Options.SPRITE_SIZE[Options.ZOOM_LEVEL]))
        
    def move_xy(self, x, y):
        """Move cursor to absolute map (x, y)."""
        self.x = x
        if self.x < 0:
            self.x = 0
        elif self.x > (self.entities.map.width - 1):
            self.x = self.entities.map.width - 1
        self.y = y
        if self.y < 0:
            self.y = 0
        elif self.y > (self.entities.map.height - 1):
            self.y = self.entities.map.height - 1
        if Options.SHIPINFO_ON_HOVER:
            # Get the ship under cursor
            ship = self.entities.map.get_at_xy(self.pos())
            for widget in self.entities.interface:
                # If there's a ShipInfo widget already
                if isinstance(widget, Interfaces.ShipInfoContainer):
                    # If it's for the ship currently at the cursor
                    if widget.ship == ship:
                        # Just leave it there
                        return
                    # If player wants ShipInfo on selected ships and
                    # this widget's ship is selected then don't delete
                    if not (Options.SHIPINFO_ON_SELECT and widget.ship == self.entities.selected):
                        self.entities.interface.remove(widget)
            # If we have a ship under the cursor
            if ship:
                # Make a ShipInfo widget for it
                self.entities.interface.append(Interfaces.ShipInfoContainer(self.entities.interface, ship))
    
    def move(self, x, y):
        """Move cursor by (x, y) relative to current position."""
        self.move_xy(self.x + x, self.y - y)
            
    def move_screen_xy(self, pos):
        """Translate screen (x, y) to map (x, y) and move cursor there.
        
        If screen (x, y) is on map, move cursor and return True;
        Otherwise, return False
        """
        x, y = self.entities.map.map_location(pos)
        # If map (x, y) exists on map
        if x <= self.entities.map.width and \
        x >= 0 and \
        y <= self.entities.map.height and \
        y >= 0:
            # Move cursor
            self.move_xy(x, y)
            return True
        # If map (x, y) off the map
        return False
    
    def pos(self):
        return self.x, self.y
        
class EffectsHandler():
    def __init__(self):
        self.lower = []
        self.higher = []
        
    def add(self, effect):
        if effect.r < 2 and effect.r > 5:
            self.higher.append(effect)
        else:
            self.lower.append(effect)
            
    def add_higher(self, effect):
        self.higher.append(effect)
    
    def add_lower(self, effect):
        self.lower.append(effect)
        
    def poll(self):
        for item in self.lower:
            item.poll()
            if item.life_time == 0:
                self.lower.remove(item)
                
        for item in self.higher:
            item.poll()
            if item.life_time == 0:
                self.higher.remove(item)
   
class EntityHandler():
    def __init__(self, view, tile_graphics, ship_graphics, graphics):
        self.players = Players.Players()
        
        self.selected = None # selected ship.
        
        self.tile_graphics = tile_graphics
        self.ship_graphics = ship_graphics
        self.graphics = graphics

        self.clouds = []
        self.effects = EffectsHandler()
        self.night = 20 # how dark is it? 255  = er... cant see shit. 0 = day.
        # !!!
        # 85 is the point that lights need to go on and off!
        # !!!
        self.night_surface = pygame.Surface(pygame.display.list_modes()[0])
        self.interface = Interfaces.Interface()
        self.interface.rect = view.rect
        self.view = view
        
    def select(self):
        old = self.selected
        self.deselect()
        for player in self.players.values():
            # For each ship in each player
            for ship in player.ships.values():
                # If ship at the cursor
                if ship.x == self.cursor.x and ship.y == self.cursor.y:
                    # Select the ship
                    self.selected = ship
                    ship.select()
                    if Options.SHIPINFO_ON_SELECT:
                        for widget in self.interface:
                            # For each ShipInfo widget
                            if isinstance(widget, Interfaces.ShipInfoContainer):
                                # If we already have a ShipInfo widget for the selected ship
                                if widget.ship == self.selected:
                                    # Don't make a new one
                                    self.interface.remove(widget)
                        # Create one
                        self.interface.append(Interfaces.ShipInfoContainer(self.interface, self.selected))
                    # Reset the select counter (makes cursor flash)
                    self.view.selected_counter = 0
                    #if old == self.selected:
                        #self.view.pan_to_ship(self.selected, 20)
                    # Return True if we selected a ship
                    return True
        # Return False if there was no ship to select
        return False
    
    def deselect(self):
        # If we have selected a ship
        if self.selected:
            for widget in self.interface[:]:
                # Remove any Weapon widgets
                if isinstance(widget, Interfaces.Weapon):
                    self.interface.remove(widget)
            if Options.SHIPINFO_ON_SELECT:
                for widget in self.interface:
                    # For each ShipInfo widget
                    if isinstance(widget, Interfaces.ShipInfoContainer):
                        # If the widget's ship is the selected ship
                        if widget.ship == self.selected:
                            # If we're not hovering over the widget and the player wants ShipInfo on hover
                            if not (Options.SHIPINFO_ON_HOVER and self.cursor.pos() == (widget.ship.x, widget.ship.y)):
                                # Delete the ShipInfo widget
                                self.interface.remove(widget)
            # Deselect the ship
            self.selected.deselect()
            self.selected = None
        
# main stuff.

    def addEffect(self, lifeTime, x, y):
        self.effects.append(Effects.Effect(self, lifeTime, 0, x, y, 0))

    def addCloud(self, x, y, colour):
        self.clouds.append(Clouds.Cloud(self, x, y, colour))

    def poll(self):
        if self.night <= 20:
            self.night_surface.fill((252, 159, 28)) #yellow morning
        elif self.night > 20 and self.night <= 50:
            self.night_surface.fill((190, 76, 18)) #orange evening
        elif self.night >50 and self.night <= 150:
            self.night_surface.fill((14, 82, 125)) # early evening
        elif self.night >150 and self.night <= 180:
            self.night_surface.fill((7, 36, 53)) # dusk
        #elif self.night >180 and self.night <= 200:
        #    self.night_surface.fill((9, 24, 78)) # evening
        elif self.night >180 and self.night <= 220:
            self.night_surface.fill((6, 9, 56)) # moonlit night
        else:
            self.night_surface.fill((3, 8, 32)) # dark night
            
        for player in self.players.values():
            for ship in player.ships.values():
                ship.poll()
            
        self.effects.poll()
                
        self.interface.update()
        
    def all(self):
        r = [self.cursor]
        for player in self.players.values():
            for ship in player.ships.values():
                r.append(ship)
        r += self.clouds
        return r
        
